const Utils = require(".");
const Redis = require("./Redis");
const tokenExpire = Utils.getConfig().tokenExpire;

class Token {
  /**
   * 将账户信息生成token存入Redis
   */
  static saveToken(userInfo) {
    return new Promise(async (resolve, reject) => {
      if (!userInfo || !userInfo.account) {
        reject({ code: 400, message: "用户不存在" });
        return;
      }
      try {
        const { account } = userInfo;
        const token = Token.createToken();
        // 删除之前的token
        await Token.deleteByAccount(account);
        // 将账号存入token
        await Redis.set(`token-account:${token}`, account, "EX", tokenExpire);
        // 将token存入账号
        await Redis.set(`account-token:${account}`, token, "EX", tokenExpire);
        await Token.saveInfo(userInfo);
        resolve(token);
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 保存账号信息
   */
  static saveInfo(userInfo) {
    return new Promise(async (resolve, reject) => {
      try {
        const res = await Redis.set(`account-info:${userInfo.account}`, JSON.stringify(userInfo));
        resolve(res);
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 根据账号获取账户信息
   */
  static getInfoByAccount(account) {
    return new Promise(async (resolve, reject) => {
      try {
        const res = await Redis.get(`account-info:${account}`);
        if (!res) {
          resolve(null);
          return;
        }
        resolve(JSON.parse(res));
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 根据token获取账户信息
   */
  static getInfoByToken(token) {
    return new Promise(async (resolve, reject) => {
      try {
        const account = await Redis.get(`token-account:${token}`);
        if (!account) {
          return reject({ code: 401, message: "请先登录！" });
        }
        // 验证账号中存的token是否一致
        const t = await Redis.get(`account-token:${account}`);
        if (t !== token) {
          return reject({ code: 401, message: "账号已在其他地方登录！" });
        }
        const info = await Token.getInfoByAccount(account);
        if (!info || !info.account) {
          return reject({ code: 401, message: "登录状态异常！" });
        }
        resolve(info);
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 根据账号删除token
   */
  static deleteByAccount(account) {
    return new Promise(async (resolve, reject) => {
      try {
        // 根据账号获取token
        const token = await Redis.get(`account-token:${account}`);
        if (token) {
          await Token.delete(token);
        }
        resolve();
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 删除指定token
   */
  static delete(token) {
    return new Promise(async (resolve, reject) => {
      try {
        await Redis.del(`token-account:${token}`);
        resolve();
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 更新token有效期
   */
  static updateExpire(token) {
    return new Promise(async (resolve, reject) => {
      try {
        await Redis.expire(`token-account:${token}`, tokenExpire);
        const account = await Redis.get(`token-account:${token}`);
        await Redis.expire(`account-token:${account}`, tokenExpire);
        resolve();
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 生成token
   */
  static createToken() {
    let token = `t-${Date.now().toString(32)}`;
    for (let i = 0; i < 10; i++) {
      token += Math.floor(Math.random() * 32).toString(32);
    }
    return token;
  }
}

module.exports = Token;
